//
// Engine.cs
//
// Copyright (C) 2008 Lukas Lipka <lukaslipka@gmail.com>
//

using System;
using System.IO;
using System.Collections.Generic;

using NDesk.DBus;
using org.freedesktop.DBus;

using Dashboard;
using Dashboard.Engine.Metadata;
using Dashboard.Engine.Fidelity;

namespace Dashboard.Engine
{
	public static class Engine
	{
		private const string interface_name = "org.gnome.Dashboard";

		private static Queue<IService> initialize_queue = null;
		private static Stack<IService> service_stack = null;

		// Engine services

		private static Log log = null;
		private static NetworkManager network_manager = null;
		private static MessageBroker message_broker = null;
		private static MetadataStore metadata_store = null;
		private static BackendManager backend_manager = null;
		private static ComponentManager component_manager = null;
		private static FidelityTracker fidelity_tracker = null;
		
		static Engine ()
		{
			// Construct and queue engine services for
			// initialization

			initialize_queue = new Queue<IService> ();
			service_stack = new Stack<IService> ();

			log = new Log ();
			QueueService (log);

			network_manager = new NetworkManager ();
			QueueService (network_manager);

			message_broker = new MessageBroker ();
			QueueService (message_broker);

			metadata_store = new MetadataStore ();
			QueueService (metadata_store);

			backend_manager = new BackendManager ();
			QueueService (backend_manager);

			component_manager = new ComponentManager ();
			QueueService (component_manager);

			fidelity_tracker = new FidelityTracker ();
			QueueService (fidelity_tracker);
		}
		
		public static void Initialize ()
		{
			try {
				NDesk.DBus.BusG.Init ();

				// FIXME: Allowing only one instance is sucky,
				// until we have expose the entire engine API
				// over D-Bus
				if (Bus.Session.RequestName (interface_name) != RequestNameReply.PrimaryOwner) {
					Console.WriteLine ("There is already an instance of Dashboard running!");
					Environment.Exit (1);
				}
			} catch (Exception e) {
				Console.WriteLine ("Failed to initialize DBus - {0}", e.Message);
			}

			try {
				InitializeServices ();
			} catch (Exception e) {
				Console.WriteLine ("Caught an exception trying to initialize the engine:");
				Console.WriteLine (e);
			}

			// Send a message that the engine was initialized

			message_broker.Send (new Message ("/event/engine/initialized"));
		}

		public static void Dispose ()
		{
			// Send a message that the engine is just
			// about to get disposed

			message_broker.Send (new Message ("/event/engine/dispose"));

			// Dispose of all our service in the order
			// that they were started
			
			while (service_stack.Count > 0)
				DisposeService (service_stack.Pop ());
		}

		private static void InitializeServices ()
		{
			while (initialize_queue.Count > 0) {
				IService service = initialize_queue.Dequeue ();

				service.Initialize ();
				service_stack.Push (service);
			}
		}

		private static void QueueService (IService service)
		{
			initialize_queue.Enqueue (service);
		}

		private static void DisposeService (IService service)
		{
			service.Dispose ();
		}

		public static Log Log {
			get { return log; }
		}
		
		public static MessageBroker MessageBroker {
			get { return message_broker; }
		}
		
		public static BackendManager BackendManager {
			get { return backend_manager; }
		}

		public static ComponentManager ComponentManager {
			get { return component_manager; }
		}

		public static MetadataStore MetadataStore {
			get { return metadata_store; }
		}

		public static NetworkManager NetworkManager {
			get { return network_manager; }
		}
	}
}
